package ch.ethz.fcl.view;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.ArrayList;
import java.util.List;

import org.opencv.core.Point;

import ch.ethz.fcl.Constant;
import ch.ethz.fcl.KinectContainer;
import ch.ethz.fcl.input.Coordinate;
import ch.ethz.fcl.process.polygon.Polygon;
import ch.ethz.fcl.tools.Tools;

public class TableView extends Component {
	private static final long serialVersionUID = 6435753404240318720L;

	private KinectContainer container;
	protected int width, height;

	private List<Polygon> polygons;

	private int tableMinX = 10, tableMinY = 10, tableMaxX = 510,
			tableMaxY = 510;

	private int tableWidth = 500, tableHeight = 500;

	public TableView(KinectContainer container) {
		this.width = 520;
		this.height = 520;
		this.container = container;
	}

	public void reset() {
		polygons = new ArrayList<Polygon>();
	}

	public void addPolygons(List<Polygon> inputPolygons) {
		polygons.addAll(inputPolygons);
	}

	@Override
	public Dimension getPreferredSize() {
		return new Dimension(width, height);
	}

	@Override
	public void paint(Graphics g) {
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		g.setColor(Color.BLACK);
		g.drawLine(tableMinX, tableMinY, tableMaxX, tableMinY);
		g.drawLine(tableMaxX, tableMinY, tableMaxX, tableMaxY);
		g.drawLine(tableMaxX, tableMaxY, tableMinX, tableMaxY);
		g.drawLine(tableMinX, tableMinY, tableMinX, tableMaxY);

		if (polygons != null)
			for (int i = 0; i < polygons.size(); i++) {
				Polygon polygon = polygons.get(i);

				if (polygon == null)
					continue;

				List<Point> pointsOnTable = new ArrayList<Point>();

				if (Constant.DEBUG)
					System.out.println("polygon height " + polygon.getHeight());

				float centerX = 0, centerY = 0;
				for (int j = 0; j < polygon.getPoints().size(); j++) {
					Point p = polygon.getPoints().get(j);
					float x = (float) p.x, y = (float) p.y;

					int inBoundRow = (int) Tools.inBound(y,
							Coordinate.TABLE_INBOUND_MIN_Y,
							Coordinate.TABLE_INBOUND_MAX_Y);
					int inBoundCol = (int) Tools.inBound(x,
							Coordinate.TABLE_INBOUND_MIN_X,
							Coordinate.TABLE_INBOUND_MAX_X);

					double[] imagePos = Coordinate
							.groundImagePosition(
									x,
									y,
									container.getTableDepthMap()
											.getGroundDepthMap()[inBoundRow][inBoundCol],
									polygon.getHeight());
					double[] tablePos = Coordinate.getPositionOnTable(
							imagePos[0], imagePos[1], tableWidth, tableHeight);

					pointsOnTable.add(new Point(tablePos[0], tablePos[1]));

					if (Constant.DEBUG) {
						System.out.print(polygon.getHeight() + ", ");
						System.out.print("(" + (int) x + "," + (int) y + "), ");
						System.out.print("(" + imagePos[0] + "," + imagePos[1]
								+ "), ");
						System.out.print("(" + (int) tablePos[0] * 2 + ","
								+ (int) tablePos[1] * 2 + "); ");
					}

					centerX += (tablePos[0] + tableMinX);
					centerY += (tableMaxY - tablePos[1]);
				}
				if (Constant.DEBUG)
					System.out.println();
				centerX /= pointsOnTable.size();
				centerY /= pointsOnTable.size();

				if (Constant.DEBUG) {
					float width = Float.MAX_VALUE, length = -1;
					for (int j = 0; j < pointsOnTable.size(); j++) {
						Point p1 = pointsOnTable.get(j);
						Point p2 = pointsOnTable.get((j + 1)
								% pointsOnTable.size());
						float dist = Tools.dist(p1, p2);
						width = Math.min(width, dist);
						length = Math.max(length, dist);
					}
					System.out.println("Polygon: height " + polygon.getHeight()
							+ " width " + width * 2 + " length " + length * 2);
				}
				g.setColor(Color.BLUE);
				g.drawString("" + polygon.getHeight(), (int) centerX,
						(int) centerY);

				g.setColor(Color.red);
				paintPolygon(g, pointsOnTable);
			}
	}

	private void paintPolygon(Graphics g, List<Point> pts) {
		for (int i = 0; i < pts.size(); i++) {
			Point p0 = pts.get(i);
			Point p1 = pts.get((i + 1) % pts.size());

			g.drawLine((int) p0.x + this.tableMinX, tableMaxY - (int) p0.y,
					(int) p1.x + this.tableMinX, tableMaxY - (int) p1.y);
		}
	}
}
